/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package technotheist.data;

import technotheist.data.BVec.BVecF;
import technotheist.data.wrap.BMatrix2D;
import technotheist.data.wrap.BMatrix3D;
import technotheist.data.BVec.Size;
import technotheist.data.wrap.VecBuffer;

/**
 *
 * @author Mitch
 */
public abstract class BufferManager {

    public <T> BBuffer<T> createTBuffer(Class type, int size) {
	return createTBuffer(type, null, size);
    }
    
    public <T> BBuffer<T> createTBuffer(Class type, Size vs, int size) {
	if (vs == null) {
	    if (type == Float.TYPE) {
		return (BBuffer<T>) this.createFloatBuffer(size);
	    } else if (type == Integer.TYPE) {
		return (BBuffer<T>) this.createIntBuffer(size);
	    } else if (type == Byte.TYPE) {
		return (BBuffer<T>) this.createByteBuffer(size);
	    } else if (type == Short.TYPE) {
		return (BBuffer<T>) this.createShortBuffer(size);
	    } else if (type == Long.TYPE) {
		return (BBuffer<T>) this.createLongBuffer(size);
	    } else if (type == Double.TYPE) {
		return (BBuffer<T>) this.createDoubleBuffer(size);
	    }
	} else {
	    if (type == Float.TYPE) {
		return (BBuffer<T>) this.createVecBuffer(this.createFloatBuffer(size * vs.elems), vs);
	    } else if (type == Integer.TYPE) {
		return (BBuffer<T>) this.createVecBuffer(this.createIntBuffer(size), vs);
	    } else if (type == Byte.TYPE) {
		return (BBuffer<T>) this.createVecBuffer(this.createByteBuffer(size), vs);
	    } else if (type == Short.TYPE) {
		return (BBuffer<T>) this.createVecBuffer(this.createShortBuffer(size), vs);
	    } else if (type == Long.TYPE) {
		return (BBuffer<T>) this.createVecBuffer(this.createLongBuffer(size), vs);
	    } else if (type == Double.TYPE) {
		return (BBuffer<T>) this.createVecBuffer(this.createDoubleBuffer(size), vs);
	    }
	}
	return null;
    }

    public abstract BBuffer<Float> createFloatBuffer(int size);

    public abstract BBuffer<Double> createDoubleBuffer(int size);

    public abstract BBuffer<Integer> createIntBuffer(int size);

    public abstract BBuffer<Byte> createByteBuffer(int size);

    public abstract BBuffer<Short> createShortBuffer(int size);

    public abstract BBuffer<Long> createLongBuffer(int size);

    public <T> BMatrix2D<T> createMatrix2D(BBuffer<T> src, int x, int y) {
	return new BMatrix2D<>(src, x, y);
    }

    public <T> BMatrix3D<T> createMatrix3D(BBuffer<T> src, int x, int y, int z) {
	return new BMatrix3D<>(src, x, y, z);
    }

    public <T extends Number> VecBuffer<T> createVecBuffer(BBuffer<T> src, Size size) {
	return new VecBuffer<>(src, size, src.size() / size.elems);
    }

    public BMatrix2D<Float> createFloatMatrix2D(int x, int y) {
	BBuffer<Float> fb = createFloatBuffer(x * y);
	return new BMatrix2D<>(fb, x, y);
    }

    public BMatrix2D<Integer> createIntMatrix2D(int x, int y) {
	BBuffer<Integer> fb = createIntBuffer(x * y);
	return new BMatrix2D<>(fb, x, y);
    }

    public BMatrix2D<Byte> createByteMatrix2D(int x, int y) {
	BBuffer<Byte> fb = createByteBuffer(x * y);
	return new BMatrix2D<>(fb, x, y);
    }

    public BMatrix3D<Float> createFloatMatrix3D(int x, int y, int z) {
	BBuffer<Float> fb = createFloatBuffer(x * y * z);
	return new BMatrix3D<>(fb, x, y, z);
    }

    public BMatrix3D<Integer> createIntMatrix3D(int x, int y, int z) {
	BBuffer<Integer> fb = createIntBuffer(x * y * z);
	return new BMatrix3D<>(fb, x, y, z);
    }

    public BMatrix3D<Byte> createByteMatrix3D(int x, int y, int z) {
	BBuffer<Byte> fb = createByteBuffer(x * y * z);
	return new BMatrix3D<>(fb, x, y, z);
    }

    public BMatrix3D<BVec<Float>> createVecVolume(int x, int y, int z, Size vsize) {
	BBuffer<Float> fb = createFloatBuffer(x * y * z * 3);
	VecBuffer<Float> vb = createVecBuffer(fb, vsize);
	return createMatrix3D(vb, x, y, z);
    }

}
